package JavaUtils.weData;

import JavaUtils.Action.*;
import JavaUtils.CSUtils.AAttribute.AField;
import JavaUtils.CSUtils.Log.CLog;
import JavaUtils.CSUtils.*;

import java.lang.reflect.Type;
import java.util.*;

public abstract class We_DataBase {
    static final String tag = "We_DataBase";
    /// <summary>
    /// 类型注册表
    /// </summary>
    static Map<CInt4, We_DataBase> ee_byte4_register = new HashMap<>();
    static Map<Class, CInt4> ee_type_register = new HashMap<>();
    public static Action3<We_DataBase, String, Object> d_RegisterWeDataEvent;

    public static void S_RegisterWeDataType(int a, int b, int c, int d, We_DataBase dataObj, String tag, Object linkObj) {
        CInt4 typeId = dataObj.m_typeId();
        if (ee_byte4_register.containsKey(typeId)) {
            CLog.ef("We_DataBase.注册出错,类型重复___.%s.___.%s...........%s.", typeId.toString(), dataObj.getClass().getName(), ee_byte4_register.get(typeId).getClass().getName());
            //return;
        }

        ee_byte4_register.put(typeId, dataObj);
        ee_type_register.put(dataObj.getClass(), typeId);
        CBaseType_Extend.S_AddAssembly(dataObj.getClass().getPackage());
        try {
            if (d_RegisterWeDataEvent != null) {
                d_RegisterWeDataEvent.Invoke(dataObj, tag, linkObj);
            }
        } catch (Exception ex) {
            CLog.ex(tag,"We_DataBase.注册出错,___", ex);
        }
        String ss0 = typeId.toString();
        String ss1 = dataObj.getClass().getName();
        String ss2 = ee_byte4_register.get(typeId).getClass().getName();
        CLog.f("We_DataBase.注册___.%s.___.%s...%s", typeId.toString(), dataObj.getClass().getName(), ee_byte4_register.get(typeId).getClass().getName());

    }

    public static void S_RegisterWeDataTypeClear() {
        ee_byte4_register.clear();
        ee_type_register.clear();
    }

    public static We_DataBase S_GetNewObj(CInt4 onlyType) {
        if (!We_DataBase.ee_byte4_register.containsKey(onlyType)) {
            CLog.ef(tag,"We注册表.不存在dataType......{0}", onlyType);
            return null;
        }
        return We_DataBase.ee_byte4_register.get(onlyType).S_GetNewObj();
    }

    public static We_DataBase S_GetNewObj(Type type) {
        if (!We_DataBase.ee_type_register.containsKey(type)) {
            CLog.ef("We注册表.不存在dataType......{0}", type.getTypeName());
            return null;
        }
        return S_GetNewObj(We_DataBase.ee_type_register.get(type));
    }

    public static CInt4 S_GetDataTypeId(Type type) {
        if (!We_DataBase.ee_type_register.containsKey(type)) {
            CLog.ef("We注册表.不存在dataType......{0}", type.getTypeName());
            return null;
        }
        return We_DataBase.ee_type_register.get(type);
    }

    public static We_DataBase[] S_FindRegisterTypeB(int bb) {
        Object[] objArray = CLinq.where(ee_byte4_register.keySet(), new Pre<CInt4>() {
            @Override
            public boolean check(CInt4 n) {
                return n.b() == bb;
            }
        }).toArray();
        return (We_DataBase[]) objArray;
    }

    public int m_SerializableId;

    public abstract CInt4 m_typeId();

    public static final CInt4 m_TypeId = CInt4.Get(0, 0, 0, 1);

    public abstract String m_typeTag();

    public static final String m_TypeTag = "行为树";

    public abstract We_DataBase S_GetNewObj();

    public void Clear() {
        //ClearData();
        ClearData();
    }

    /// <summary>
    /// 需要子类继承的方法
    /// </summary>
    //protected abstract void ClearData();

    protected abstract void ClearData();

    public abstract void toString(StringBuilder ssb);

    /// <summary>
    /// 获取子物体的所有结构体对象
    /// </summary>
    public abstract We_DataBase[] S_GetClassObjs();

    public abstract AField[] S_GetWeFields();

    public abstract Map<Byte, AField> S_GetWeFieldDic();

    public abstract Object S_IndexField(int fieldIndex, boolean isGet, Object obj);

    /// <summary>
    /// 需要子类继承的方法
    /// </summary>
    //protected abstract void S_Serializable();

    protected abstract void S_SerializableByte(BinaryWriter binaryWriter);

    /// <summary>
    /// 需要子类继承的方法
    /// </summary>
    //protected abstract void S_DeSerialization();

    protected abstract void S_DeSerializationByte(BinaryReader binaryReader, Map<Integer, We_DataBase> uintObjDic, long endPosition);


    protected abstract void S_SerializableString(StringBuilder ssb, boolean isExplain);

    protected abstract void S_DeSerializationString(String[] sss, Map<Integer, We_DataBase> uintObjDic);

    /// <summary>
    /// 加载文本数据
    /// </summary>
    public void S_LoadTxtData(String[] sss) {
        if (sss == null) {
            return;
        }
        Map<Integer, We_DataBase> uintObjDic = new HashMap<Integer, We_DataBase>();
        S_DeSerializationString(sss, uintObjDic);
    }

    public abstract void S_Copy(We_DataBase obj0);

    public void S_LoadBytesData(byte[] bytes) {
        //Stream stream = new MemoryStream(bytes);
        BinaryReader binaryReader = new BinaryReader(bytes);
        S_DeSerializationByte(binaryReader, null, bytes.length);
    }

    // #region--------------Byte.序列化----------------------------
    //数据头类型,长度,类型1对象id,字段索引,字段值
    public static byte[] S_SerializableByte(Object obj) {
        if (obj == null) {
            CLog.ef(tag,"超级出错误.....array==null_____无法序列化");
            return null;
        }
        //1.获取<<结构体对象列表>>
        List<We_DataBase> objList = new ArrayList<We_DataBase>();
        //2.遍历<<结构体对象列表>>序列化
        //MemoryStream memoryStream = new MemoryStream();
        BinaryWriter binaryWriter = new BinaryWriter();
        if (obj.getClass().isArray()) {
            binaryWriter.Write((byte) EBaseType.e018_array); //0,数据头类型
            List<Integer> arrayList = new ArrayList<>();
            We_DataBase[] arr = (We_DataBase[]) obj;
            for (We_DataBase obj2 : arr) {
                if (obj2 == null) {
                    continue;
                }
                S_Recursion(obj2, objList);
                arrayList.add(obj2.m_SerializableId);
            }
            binaryWriter.Write((int) arrayList.size()); //1,数组长度---
            for (Integer integer : arrayList) {
                binaryWriter.Write(integer);   //2,数组元素ID---
            }
        } else {
            binaryWriter.Write((byte) EBaseType.e021_weData);
            S_Recursion((We_DataBase) obj, objList);
        }
        for (We_DataBase we_dataBase : objList) {
            we_dataBase.S_SerializableByte(binaryWriter);
        }
        //CLog0.LogErrorFormat("完成的长度____{0}.____.{1}____.{2}", memoryStream.GetBuffer().Length, binaryWriter.BaseStream.Position, memoryStream.Length);
        return binaryWriter.S_ToBytes();
    }

    static void S_Recursion(We_DataBase data, List<We_DataBase> objList) {
        if (data == null) {
            CLog.wf(tag,"数据对象==null");
            return;
        }
        if (objList.contains(data)) {
            //CLog.LogWarningFormat("数据对象。已经在列表中了");
            return;
        }
        //data.S_Serializable();
        objList.set(objList.size(), data);
        data.m_SerializableId = objList.size();
        We_DataBase[] objs = data.S_GetClassObjs();
        for (We_DataBase obj : objs) {
            S_Recursion(obj, objList);
        }
    }
    //#endregion---------------Byte.序列化--------------------------------------------


    //#region-------------------Byte.反序列化--------------------------------------------
    public static <T extends We_DataBase> T[] S_DeSerializationBytes(byte[] bytes) {
        Object obj = S_DeSerializationByte(bytes, false);
        if (S_DeSerializationByte_isArray) {
            return S_ToArray(obj);
        } else {
            CLog.ex(tag,"不是数组无法完成反序列化..............");
            return null;
        }
    }

    public static <T extends We_DataBase> T[] S_ToArray(Object obj) {
        if (obj.getClass().isArray()) {
            return (T[]) obj;
        }
        return null;
    }

    public static <T extends We_DataBase> T S_DeSerializationByte(byte[] bytes) {
        Object obj = S_DeSerializationByte(bytes, false);
        if (S_DeSerializationByte_isArray) {
            CLog.ex(tag,"是数组无法完成反序列化..............");
            return null;
        } else {
            return (T) obj;
        }
    }

    static boolean S_DeSerializationByte_isArray;

    public static Object S_DeSerializationByte(byte[] bytes, boolean isArray) {
//        //CLog0.LogErrorFormat("解析的长度____{0}", bytes.Length);
//        //1.获取<<结构体对象列表>>
        Object _data = null;
        //Stream stream = new MemoryStream(bytes);
        BinaryReader binaryReader = new BinaryReader(bytes);
        Map<Integer, We_DataBase> uintObjDic = new HashMap<>();
        int type = binaryReader.ReadByte();
        if (type == EBaseType.e018_array) {
            int[] array0 = new int[binaryReader.ReadInt32()];
            for (int i = 0; i < array0.length; i++) {
                array0[i] = binaryReader.ReadInt32();
            }
            _data = array0;
        }
        while (binaryReader.readerIndex < binaryReader.Length) {
            We_DataBase data = S_ReadObj(binaryReader);
            if (data != null) {
                uintObjDic.put(data.m_SerializableId, data);
                if (_data == null) {
                    _data = data;
                }
                binaryReader.readerIndex = data.endPosition;
            }
        }
        //2.遍历<<结构体对象列表>>反序列化
        We_DataBase[] array4 = new We_DataBase[uintObjDic.size()];
        uintObjDic.values().toArray(array4);
        for (We_DataBase we_dataBase : array4) {
            //try {
            binaryReader.readerIndex = we_dataBase.startPosition;
            we_dataBase.S_DeSerializationByte(binaryReader, uintObjDic, we_dataBase.endPosition);
            //} catch { }
        }
//        for (int i = 0; i < array4.length; i++) {
//            try {
//                array4[i].S_DeSerialization();
//            } catch (Exception ex) {
//                CLog.LogErrorInfo("错误." + i + "_" + uintObjDic.size(), ex, true);
//            }
//        }
        if (type == EBaseType.e018_array) {
            S_DeSerializationByte_isArray = true;
            int[] array0 = (int[]) _data;
            We_DataBase[] array = new We_DataBase[array0.length];
            for (int i = 0; i < array0.length; i++) {
                if (uintObjDic.containsKey(array0[i])) {
                    array[i] = uintObjDic.get(array0[i]);
                }
            }
            _data = array;
        } else {
            S_DeSerializationByte_isArray = false;
        }
        return _data;
    }

    int startPosition, endPosition;

    static We_DataBase S_ReadObj(BinaryReader binaryReader) {
        int type = binaryReader.ReadInt32();
        int instanceId = binaryReader.ReadInt32();
        int byteLenght = binaryReader.ReadInt32();
        //CLog0.LogErrorFormat("获取对象._____.{0}.{1}.{2}.___length={3}______", type1, type2, type3, byteLenght);
        We_DataBase data = S_GetNewObj(CInt4.Get(type, false));
        if (data == null) {
            return null;
        }
        data.m_SerializableId = instanceId;
        data.startPosition = binaryReader.readerIndex;
        data.endPosition = data.startPosition + byteLenght;
        return data;
    }
    //  #endregion--------------Byte.反序列化--------------------------------------------


    //   #region-----------------序列化.string.----------------------------
    //长度,类型1,类型2,对象id,字段索引,字段值
    public static String S_SerializableString(Object obj, boolean isAddExplain) {
        //2.获取<<结构体对象列表>>
        List<We_DataBase> objList = new ArrayList<We_DataBase>();
        //1.遍历<<结构体对象列表>>序列化
        StringBuilder ssb = new StringBuilder();
        if (obj.getClass().isArray()) {
            ssb.append(((byte) EBaseType.e018_array));
            List<Integer> arrayList = new ArrayList<Integer>();
            We_DataBase[] arr = (We_DataBase[]) obj;
            for (We_DataBase obj2 : arr) {
                if (obj2 == null) {
                    continue;
                }
                S_Recursion(obj2, objList);
                arrayList.add(obj2.m_SerializableId);
            }
            ssb.append(" {0}{1} ", CString.cSplit06, arrayList.size());
            for (Integer integer : arrayList) {
                ssb.append(" {0}{1} ", CString.cSplit06, integer); //2,数组元素ID---
            }
        } else {
            ssb.append(((byte) EBaseType.e021_weData));
            S_Recursion((We_DataBase) obj, objList);
        }
        ssb.append("\r\n" + CString.cSplit08);
        We_DataBase[] array = new We_DataBase[objList.size()];
        objList.toArray(array);
        for (We_DataBase we_dataBase : array) {
            //CLog0.LogErrorFormat("_______{0}___", dic.Current.getClass().FullName);
            we_dataBase.S_SerializableString(ssb, isAddExplain);
            ssb.append("\r\n" + CString.cSplit08);
        }
        //CLog0.LogErrorFormat("完成的长度____{0}.____.{1}____.{2}", memoryStream.GetBuffer().Length, binaryWriter.BaseStream.Position, memoryStream.Length);
        return ssb.toString();
    }


    public static <T extends We_DataBase> T[] S_DeSerializationStrings(String content) {
        Object obj = S_DeSerializationString(content, false);
        if (S_DeSerializationString_isArray) {
            return S_ToArray(obj);
        } else {
            CLog.ex(tag,"不是数组无法完成反序列化..............");
            return null;
        }
    }

    public static <T extends We_DataBase> T S_DeSerializationString(String content) {
        We_DataBase obj = (We_DataBase) S_DeSerializationString(content, false);
        if (S_DeSerializationString_isArray) {
            CLog.ex(tag,"是数组无法完成反序列化..............");
            return null;
        } else {
            return (T) obj;
        }
    }

    static boolean S_DeSerializationString_isArray;

    public static Object S_DeSerializationString(String content, boolean bb) {
        Object _data = null;
        String[] sssLine = CString.string_split(content, CString.cSplit08);
        //CLog.LogErrorFormat("S_DeSerializationString..解析的行数____{0}", sssLine.Length);
        String[] sss0 = CString.string_split(sssLine[0], CString.cSplit06 + "", "\r\n");
        int type = Integer.parseInt(sss0[0]);
        if (type == EBaseType.e018_array) {
            int[] array0 = new int[Integer.parseInt(sss0[1])];
            for (int i = 0; i < array0.length; i++) {
                array0[i] = Integer.parseInt(sss0[i + 2]);
            }
            _data = array0;
        }
        //1.获取<<结构体对象列表>>
        Map<Integer, We_DataBase> uintObjDic = new HashMap<Integer, We_DataBase>();
        Map<Integer, String[]> uintStringsDic = new HashMap<Integer, String[]>();
        for (int i = 1; i < sssLine.length; i++) {
            String[] sss = sssLine[i].split(CString.cSplit06 + "");
            try {
                //string[] typeIds = sss[0].Split(new string[] { "=", ";", "\t", "\n", "\r\n", "/", " " }, StringSplitOptions.RemoveEmptyEntries);
                CInt4 typeId = CInt4.Get(sss[0], false);
                String[] instanceIds = CString.string_split(sss[1], "=", ";", "\t", "\n", "\r\n", "/", " ");
                int instanceId = Integer.parseInt(instanceIds[0]);
                We_DataBase data = S_GetNewObj(typeId);
                if (data != null) {
                    data.m_SerializableId = instanceId;
                    uintObjDic.put(data.m_SerializableId, data);
                    uintStringsDic.put(data.m_SerializableId, sss);
                    if (_data == null) {
                        _data = data;
                    }
                }
            } catch (Exception ignored) {
            }
        }
        We_DataBase[] array4 = new We_DataBase[uintObjDic.size()];
        uintObjDic.values().toArray(array4);
        for (int i = 0; i < array4.length; i++) {
            try {
                array4[i].S_DeSerializationString(uintStringsDic.get(array4[i].m_SerializableId), uintObjDic);
            } catch (Exception ex) {
                CLog.ex(tag,"错误." + i + "_" + uintObjDic.size(), ex, false);
            }
        }
//        for (int i = 0; i < array4.length; i++) {
//            try {
//                array4[i].S_DeSerialization();
//            } catch (Exception ex) {
//                CLog.LogErrorInfo("错误." + i + "_" + uintObjDic.size(), ex, false);
//            }
//        }
        if (type == EBaseType.e018_array) {
            S_DeSerializationString_isArray = true;
            int[] array0 = (int[]) _data;
            We_DataBase[] array = new We_DataBase[array0.length];
            for (int i = 0; i < array0.length; i++) {
                if (uintObjDic.containsKey(array0[i])) {
                    array[i] = uintObjDic.get(array0[i]);
                }
            }
            _data = array;
        } else {
            S_DeSerializationString_isArray = false;
        }
        return _data;
    }

    //    #endregion------------------反序列化.string.--------------------------------------------
}
